package excelBase;

import java.util.ArrayList;

import lib.CellInLib;
import lib.MergeInLib;
import main.ErrorException;
import xml.XmlNode;
import define.Config;
import define.ErrorDefine;

public class Node extends BaseContent
{
	private ArrayList<String> m_attributeName;
	private ArrayList<String> m_attributeValue;
	private Sheet m_sheet;
	private String m_value;
	private MergeInLib m_merge;
	
	public Node(MergeInLib merge, Sheet sheet, boolean hasAttribute) throws ErrorException
	{
		super("");
		m_merge = merge;
		m_sheet = sheet;
		m_value = "";
		makeChildren(hasAttribute);
	}
	
	private void makeChildren(boolean hasAttribute) throws ErrorException
	{
		m_name = m_sheet.getCellValue(m_merge.getY1(), m_merge.getX1());
		if(hasAttribute)
		{
			makeAttribute(m_merge.getX1(), m_merge.getX2(), m_merge.getY2());
		}
		int column = m_merge.getX2() + 1;
		boolean isEmpty = true;
		for(int i = m_merge.getY1(), max = m_merge.getY2(); i <= max; ++i)
		{
			CellInLib cell = m_sheet.getCell(i, column);
			if(cell.getValue().length() != 0)
			{
				isEmpty = false;
				break;
			}
		}
		if(isEmpty)
		{
			return;
		}
		m_children = new ArrayList<>();
		for(int i = m_merge.getY1(); i <= m_merge.getY2();)
		{
			CellInLib cell = m_sheet.getCell(i, column);
			if(cell.IsEmpty())
			{
				break;
			}
			MergeInLib childMerge = m_sheet.isMergeCell(i, column);
			if(childMerge == null)
			{
				childMerge = new MergeInLib(column, i);
			}
			int row = i + childMerge.getHeight();
			short bgColor = m_sheet.getCellBgColor(row, column);
			short fgColor = m_sheet.getCellFgColor(row, column);
			short nodeBgColor = m_sheet.getCellBgColor(i, column);
			short nodeFgColor = m_sheet.getCellFgColor(i, column);
			hasAttribute = ((bgColor != Config.NO_COLOR && bgColor != m_sheet.getNotAttributeBgColor() && bgColor != nodeBgColor)
					|| (fgColor != Config.NO_COLOR && fgColor != m_sheet.getNotAttributeFgColor() && fgColor != nodeFgColor));
			m_children.add(new Node(childMerge, m_sheet, hasAttribute));
			if(hasAttribute)
			{
				MergeInLib nameMerge = m_sheet.isMergeCell(row, column);
				if(nameMerge == null)
				{
					nameMerge = new MergeInLib(column, row);
				}
				row += nameMerge.getHeight();
				MergeInLib valueMerge = m_sheet.isMergeCell(row, column);
				if(valueMerge == null)
				{
					valueMerge = new MergeInLib(column, row);
				}
				i = row + valueMerge.getHeight();
			}
			else
			{
				i = row;
			}
			if(i > m_merge.getY2() + 1)
			{
				throw new ErrorException(ErrorDefine.E_TREE_DEFINE_ERROR, m_sheet.getName() + ":" + (i - 1) + "," + column, Config.NO_POSITION);
			}
		}
		if(m_children.size() == 0)
		{
			m_children = null;
		}
	}
	
	private void makeAttribute(int start, int end, int y) throws ErrorException
	{
		m_attributeName = new ArrayList<>();
		m_attributeValue = new ArrayList<>();
		++y;
		boolean hasValue = false;
		int nameHeight = 0;
		int valueHeight = 0;
		for(; start <= end;)
		{
			MergeInLib merge = m_sheet.isMergeCell(y, start);
			String name = m_sheet.getCellValue(y, start);
			String value = "";
			if(merge == null)
			{
				merge = new MergeInLib(start, y);
			}
			if(nameHeight != 0 && nameHeight != merge.getHeight())
			{
				throw new ErrorException(ErrorDefine.E_ATTRIBUTE_HEIGHT_ERROR, m_name, Config.NO_POSITION);
			}
			nameHeight = merge.getHeight();
			value = m_sheet.getCellValue(y + nameHeight, start);
			MergeInLib valueMerge = m_sheet.isMergeCell(y + nameHeight, start);
			if(valueMerge == null)
			{
				valueMerge = new MergeInLib(start + merge.getWidth(), y);
			}
			if(valueHeight != 0 && valueHeight != valueMerge.getHeight())
			{
				throw new ErrorException(ErrorDefine.E_ATTRIBUTE_HEIGHT_ERROR, m_name, Config.NO_POSITION);
			}
			valueHeight = valueMerge.getHeight();
			if(name.length() != 0)
			{
				m_attributeName.add(name);
				m_attributeValue.add(value);
			}
			else if(value.length() != 0)
			{
				if(hasValue)
				{
					throw new ErrorException(ErrorDefine.E_DUPLICATE_VALUE_ERROR, m_name, Config.NO_POSITION);
				}
				m_value = value;
				hasValue = true;
			}
			start += merge.getWidth();
		}
		if(m_attributeName.size() == 0)
		{
			m_attributeName = null;
			m_attributeValue = null;
		}
	}
	
	public XmlNode getXmlNode()
	{
		XmlNode node = new XmlNode(m_name);
		node.setText(m_value);
		if(m_attributeName != null)
		{
			for(int i = 0, max = m_attributeName.size(); i < max; ++i)
			{
				node.addAttribute(m_attributeName.get(i), m_attributeValue.get(i));
			}
		}
		if(m_children != null)
		{
			for(BaseContent base: m_children)
			{
				node.addChild(((Node)base).getXmlNode());
			}
		}
		return node;
	}
	
	public String getValue()
	{
		return m_value;
	}
	
	public String getAttribute(String name)
	{
		for(int i = 0, max = m_attributeName.size(); i < max; ++i)
		{
			if(m_attributeName.get(i).compareTo(name) == 0)
			{
				return m_attributeValue.get(i);
			}
		}
		return null;
	}
	
	public String getAttribute(int index)
	{
		if(index >= m_attributeName.size() || index < 0)
		{
			return null;
		}
		return m_attributeValue.get(index);
	}
}
